﻿
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Security;

namespace eCom
{
	public class eComDeliveryOptionsBizRules : Syrinx.BaseBizRules
	{
		public IBizObj getSalesOrderDeliveryOptions(IApplication app, IRuleContext context, IBizObj salesOrder, bool forceGet)
		{
			IBizObj deliveryOptions = app.sessionData.get("DeliveryOptions") as IBizObj;
			if (deliveryOptions == null || forceGet)
			{
				deliveryOptions = app.bizObjMgr.create("eComDeliveryOptions");
				IBizObjList options = deliveryOptions.get("options") as IBizObjList;
				IBizObjList errors = deliveryOptions.get("errors") as IBizObjList;

				//Go through the sales order items and ensure that there is at least one shippable item.
				//If there are no shippable items, then we will not bother with getting providers.
				bool hasShippableItems = false;
				foreach (IBizObj orderItem in (IBizObjList)salesOrder.get("items"))
				{
					ShippingBoxOption option = (ShippingBoxOption)orderItem.get("product.shippingBoxOption");
					if (option != ShippingBoxOption.NotShippable)
					{
						hasShippableItems = true;
						break;
					}
				}
				deliveryOptions.put("enable", hasShippableItems);

				if (hasShippableItems)
				{
					IResults rc = context.RuleGroup.execute("getCompanyDeliveryProviders");
					IBizObjList deliveryProviders = rc.CallResults as IBizObjList;

					IRuleGroup rg = null;
					foreach (IBizObj provider in deliveryProviders)
					{
						if (rg == null)
							rg = app.ruleMgr.executeAsync("get" + provider.get("bizObjType") + "ShippingMethods", null, null, salesOrder);
						else
							rg.executeAsync("get" + provider.get("bizObjType") + "ShippingMethods", null, null, salesOrder);
					}
					if (rg != null)
					{
						rg.waitForCompletion(false);
						for (int p = 0; p < rg.numberOfResults; ++p)
						{
							IBizObj optionsInfo = rg.getCallResults(p) as IBizObj;
							IBizObjList providerShippingMethods = optionsInfo.get("options") as IBizObjList;
							if (providerShippingMethods != null)
								foreach (IBizObj shipMethod in providerShippingMethods)
									options.Add(shipMethod);
							IBizObjList providerErrors = optionsInfo.get("errors") as IBizObjList;
							if (providerErrors != null)
								foreach (IBizObj error in providerErrors)
									errors.Add(error);

						}
					}

					rc = context.RuleGroup.execute("getOrderHandlingFees");
					IBizObjList handlingFees = rc.CallResults as IBizObjList;
					foreach (IBizObj option in options)
					{
						IBizObj generalProviderFee = null;
						IBizObj specificFee = null;
						foreach (IBizObj fee in handlingFees)
							if (((IComparable)fee.get("provider.id")).CompareTo(option.get("provider.id")) == 0)
							{
								if (string.Compare((string)fee.get("deliveryMethodName"), (string)option.get("deliveryMethodName"), true) == 0)
								{
									specificFee = fee;
									break;
								}
								else if (Cmn.IsEmpty(fee.get("deliveryMethodName")))
									generalProviderFee = fee;
							}
						if (specificFee == null && generalProviderFee != null)
							specificFee = generalProviderFee;
						if (specificFee != null)
						{
							decimal actualFee = 0M;
							string bizRuleCalculator = (string)specificFee.get("bizRuleCalculator");
							if (!Cmn.IsEmpty(bizRuleCalculator))
							{
								IResults hrc = context.RuleGroup.execute(context, bizRuleCalculator, salesOrder, option, specificFee);
								if (hrc.CallResults is decimal)
								{
									decimal handlingFee = (decimal)hrc.CallResults;
									actualFee += handlingFee;
								}
							}
							else
							{
								actualFee += (decimal)specificFee.get("baseFee");
								actualFee += (decimal)option.get("total") * ((decimal)specificFee.get("percentCost") / 100M);
							}

							option.put("handlingTotal", actualFee);
						}
					}

					app.sessionData.put("DeliveryOptions", deliveryOptions);
				}
			}
			return deliveryOptions;
		}

		public void updateSalesOrderDeliveryOption(IApplication app, IRuleContext context, IBizObj salesOrder, IBizObj deliveryOption)
		{
			FlexiMap m = new FlexiMap();
			m["order"] = salesOrder;
			m["delivery"] = deliveryOption;
			m["pickupDate"] = DateTime.MinValue.CompareTo(deliveryOption.get("pickupDate")) == 0 ? null : deliveryOption.get("pickupDate");
			m["calculatedDate"] = DateTime.UtcNow;
			app.appData.put("DA.eCom.DeleteOrderDelivery", m);
			app.appData.put("DA.eCom.AddOrderDelivery", m);
		}

		public IBizObj getSalesOrderDeliveryMethodDetails(IApplication app, IRuleContext context, object resultValue, object[] inputParams)
		{
			IBizObj salesOrder = resultValue as IBizObj;
			if (salesOrder != null)
			{
				FlexiMap m = new FlexiMap();
				m["orderId"] = salesOrder.get("id");
				IBizObj delivery = app.appData.get("DA.eCom.GetOrderDelivery", m) as IBizObj;
				if (delivery != null)
					salesOrder.put("delivery", delivery);
			}

			return salesOrder;
		}

		public void postSalesOrderChange(IApplication app, IRuleContext context, object resultValue, object[] inputParams)
		{
			Swaf.BGuid.Guid orderId = inputParams[2] as Swaf.BGuid.Guid;
			app.sessionData.put("DeliveryOptions", null);
			if (orderId != null)
			{
				IResults rc = context.RuleGroup.execute("getSalesOrderDetails", orderId);
				IBizObj order = rc.CallResults as IBizObj;
				if (order != null)
				{
					rc = context.RuleGroup.execute("getArticleIdFromUniqueTitle", "ecom_sysStatus_Open", null);
					if (((Swaf.BGuid.Guid)order.get("status.id")).CompareTo(rc.CallResults) == 0)
					{
						rc = context.RuleGroup.execute(context, "getSalesOrderDeliveryOptions", order, true);
						IBizObj delivOp = rc.CallResults as IBizObj;
						if (delivOp != null)
						{
							IBizObjList options = (IBizObjList)delivOp.get("options");
							if (options != null && options.numElements > 0)
							{
								foreach (IBizObj sb in options)
									if (((IComparable)sb.get("provider.id")).CompareTo(order.get("delivery.provider.id")) == 0 &&
										((IComparable)sb.get("deliveryMethodName")).CompareTo(order.get("delivery.deliveryMethodName")) == 0)
									{
										if (((IComparable)sb.get("total")).CompareTo(order.get("delivery.total")) != 0)
										{
											order.put("delivery", sb);
											rc = App.ruleMgr.execute("updateSalesOrder", order);
											rc = App.ruleMgr.execute("updateSalesOrderDeliveryOption", order, sb);
											return;
										}
									}
							}
						}
						FlexiMap m = new FlexiMap();
						m["order"] = order;
						int c = (int)app.appData.get("DA.eCom.DeleteOrderDelivery", m);
					}
				}
			}
		}


		public string getDeliveryOptionsDisplayName(IApplication app, IRuleContext context, IBizObj orderInfo,
			Privileges editPriv, string parentBPIds, string pageName)
		{
			string templateName = "";

			if (orderInfo != null && orderInfo.get("order") != null)
			{
				if(!Cmn.IsEmpty(orderInfo.get("order.orderContact.defaultAddress.zipCode")))
					templateName = "eCom.Gui.AspNet.DeliveryMethodOptionsDisplay";
			}
			return templateName;
		}

		public IBizObjList getCompanyDeliveryProviders(IApplication app, IRuleContext context)
		{
			FlexiMap m = new FlexiMap();
			m["companyId"] = ActiveCompanyId;

			IBizObjList deliveryProviders = app.appData.get("DA.eCom.GetCompanyDeliveryProviders", m) as IBizObjList;
			return deliveryProviders;
		}
	}
}
